package org.jeecg.common.util;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.system.vo.DictModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 判断是否是法定节假日工具类
 * 法定节假日数据来源于数据字典code: statutory_holiday, 需按时维护
 *
 * @author chechen
 * @date 2022-06-17
 */
@Slf4j
@Component
public class StatutoryHolidayUtil {

    @Setter(onMethod_ = @Autowired)
    private CommonAPI commonAPI;

    /**
     * 从指定日期开始往后偏移，n个工作日（n是days 天数）
     *
     * @param now  日期
     * @param days 天数
     * @return 某一天
     */
    public DateTime nextWorkDays(Date now, int days) {
        // 偏移天数
        int offsetDay = 0;
        // 循环条件
        while (days != 0) {
            offsetDay++;
            // 如果偏移后的那天是节假日，则继续偏移
            if (isWork(DateUtil.offsetDay(now, offsetDay))) {
                days--;
            }
        }
        return DateUtil.offsetDay(now, offsetDay);
    }


    /**
     * 判断日期是否是法定节假日
     *
     * @param date 日期
     * @return true/false
     */
    public boolean isHolidays(Date date) {
        Map<String, Set<String>> statutoryHoliday = getStatutoryHoliday();

        String dateStr = DateUtil.format(date, DatePattern.NORM_DATE_FORMAT);
        // 如果日期包含在设定到法定节假日日期里，就代表日期是法定节假日
        if (statutoryHoliday.get("holidays").contains(dateStr)) {
            return true;
        }
        // 如果日期包含在设定到工作日日期里，就代表日期不是法定节假日
        if (statutoryHoliday.get("work").contains(dateStr)) {
            return false;
        }
        // 最后判断日期是否是周六日
        return DateUtil.isWeekend(date);
    }

    /**
     * 判断是否是工作日
     *
     * @param date 日期
     * @return true/false
     */
    public boolean isWork(Date date) {
        return !isHolidays(date);
    }


    /**
     * 创建设定到法定节假日map，一般用于修改了数据，重新初始化
     */
    public Map<String, Set<String>> getStatutoryHoliday() {
        return this.commonAPI.queryDictItemsByCode("statutory_holiday")
                .stream()
                .collect(Collectors.toMap(DictModel::getValue, dictModel ->
                        Arrays.stream(dictModel.getTitle().split(StringPool.COMMA))
                                .collect(Collectors.toSet())
                ));
    }

}
